﻿using System;
using System.Collections.Generic;
using System.Security.Permissions;
using System.Text;
using System.Web.UI;
using System.ComponentModel;
using System.Web;
using System.Web.UI.HtmlControls;

namespace Library.WebControls {
	[ParseChildren(true)]
	[PersistChildren(false)]
	[DesignTimeVisible(false)]
	[AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
	[AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)] 
	public class BaseControl : Control {
		protected BaseControl() {
			Initialize();
		}
		public string ConvertToArrayString(params string[] texts) {
			return ToArrayString(texts);
		}
		public static string ToArrayString(params string[] texts) {
			var builder = new StringBuilder();
			foreach (var s in texts) {
				if (String.IsNullOrEmpty(s)) {
					builder.Append("0|");
				} else {
					builder.Append(s.Length);
					builder.Append("|");
					builder.Append(s);
				}
			}
			return builder.ToString();
		}

		public static string[] FromArrayString(string arrayString) {

			if (String.IsNullOrEmpty(arrayString)) return new string[0];
			var arr = new List<String>();
			var l = "";
			for (var i = 0; i < arrayString.Length; i++) {
				var c = arrayString[i];
				if (c == '|') {
					var rl = Int32.Parse(l);
					var st = i + 1;
					var data = arrayString.Substring(st, rl);
					arr.Add(data);
					i = i + rl;
					l = "";
				} else {
					l += c;
				}
			}
			return arr.ToArray();
		}

		private void Initialize() {
			string css = StyleSheetFileName;
			if (!String.IsNullOrEmpty(css)) {
				CssFileName = BaseCssDir + css;
			}
			var effect = this as IEffectControl;
			if (effect != null) {
				InitForEffect(effect);
			}
			_clientEnable = true;
			_clientVisible = true;
		}

		private bool _clientEnable;
		[DefaultValue(true)]
		public virtual bool ClientEnable {
			get { return _clientEnable; }
			set { _clientEnable = value; }
		}

		private bool _clientVisible;
		[DefaultValue(true)]
		public virtual bool ClientVisible {
			get { return _clientVisible; }
			set { _clientVisible = value; }
		}

		protected static readonly Type BaseControlType = typeof(BaseControl);
		public static bool IsLibraryWebControlCallback(Page page) {
			try {
				return IsLibraryWebControlCallback(page.Request);
			} catch {
				return false;
			}
		}

		public static bool IsLibraryWebControlCallback(HttpRequest request) {
			return request[BaseAjaxControlCallbackParameter] == "T";
		}

		public const string UtilLib = "Util";
		public const string DragDropLib = "DragDrop";
		public const string EffectLib = "Effect";
		public const string AjaxCoreLib = "AjaxCore";
		public const string BaseCssDir = "~/style/simple/";

		protected const string BaseAjaxControlCallbackParameter = "__SPAXRQ_";

		protected bool IsLibraryWebControlsCallback {
			get {
				return IsLibraryWebControlCallback(Page);
			}
		}

		protected bool IsClientCallback {
			get {
				return IsLibraryWebControlsCallback || Page.IsCallback;
			}
		}

		protected override void OnLoad(EventArgs e) {
			base.OnLoad(e);

			if (IsLibraryWebControlsCallback)
				return;

			if (!Page.ClientScript.IsClientScriptIncludeRegistered(BaseControlType, "BaseJs")) {
				Page.ClientScript.RegisterClientScriptInclude(BaseControlType, "BaseJs", Page.ClientScript.GetWebResourceUrl(BaseControlType, "Library.WebControls.CoreJs.NameSpace.js"));
				AddLinkCssControl(BaseCssDir + "spcore-ui.css");
			}
		}

		//protected void AddScriptHandler(HtmlTextWriter writer, string key, string script, string addHandlerFunction) {

		//}
		protected void AddScriptHandler(HtmlTextWriter writer, int key, string script, string addHandlerFunction) {
			if (String.IsNullOrEmpty(script)) return;
			script = script.Trim();
			if (script.StartsWith("function")) {
				if (script.Length > 8) {
					var c = script[8];
					if (c == '(' || c == ' ') {
						writer.Write(String.Format("{0}.{1}({2},{3});", ClientName, addHandlerFunction, key, script));
						return;
					}
				}
			}
			if (script.EndsWith(";"))
				script = "function(s,e){" + script + "}";
			else script = "function(s,e){" + script + ";}";
			writer.Write(String.Format("{0}.{1}({2},{3});", ClientName, addHandlerFunction, key, script));
		}

		public void IncludeJavascriptCore(string javascriptFileNameWithoutExtension) {
			if (String.Compare(javascriptFileNameWithoutExtension, UtilLib, true) == 0) {
				javascriptFileNameWithoutExtension = UtilLib;
			} else if (String.Compare(javascriptFileNameWithoutExtension, DragDropLib, true) == 0) {
				javascriptFileNameWithoutExtension = DragDropLib;
			} else if (String.Compare(javascriptFileNameWithoutExtension, EffectLib, true) == 0) {
				javascriptFileNameWithoutExtension = EffectLib;
			} else if (String.Compare(javascriptFileNameWithoutExtension, AjaxCoreLib, true) == 0) {
				javascriptFileNameWithoutExtension = AjaxCoreLib;
			}

			if (!Page.ClientScript.IsClientScriptIncludeRegistered(BaseControlType, javascriptFileNameWithoutExtension)) {
				if (String.Compare(javascriptFileNameWithoutExtension, DragDropLib, true) == 0 || String.Compare(javascriptFileNameWithoutExtension, EffectLib, true) == 0) {
					IncludeJavascriptCore(UtilLib);
				}
				Page.ClientScript.RegisterClientScriptInclude(BaseControlType, javascriptFileNameWithoutExtension, Page.ClientScript.GetWebResourceUrl(BaseControlType, String.Format("Library.WebControls.CoreJs.{0}.js", javascriptFileNameWithoutExtension)));
			}
		}

		private string _clientName;

		public virtual string ClientName {
			get {
				if (String.IsNullOrEmpty(_clientName))
					return String.Format("{0}clientName", ClientID);
				return _clientName;
			}
			set { _clientName = value; }
		}

		internal bool ClientNameIsNull {
			get { return String.IsNullOrEmpty(_clientName); }
		}
		protected void BeginScriptTag(HtmlTextWriter writer) {
			writer.Write("<script language=\"javascript\" type=\"text/javascript\">");
		}

		protected void EndScriptTag(HtmlTextWriter writer) {
			writer.Write("</script>");
		}

		private HttpRequest _request;
		[Browsable(false)]
		public HttpRequest Request {
			get {
				if (_request == null) {
					try {
						_request = Page.Request;
					} catch (HttpException) {
						_request = null;
					} catch (Exception) {
						_request = null;
					}
				}

				return _request;
			}
		}

		protected HttpResponse Response {
			get { return Page.Response; }
		}
		internal HtmlGenericControl CreateCssLink() {
			if (String.IsNullOrEmpty((CssFileName))) return new HtmlGenericControl("div");
			return CreateCssLink(CssFileName);
		}
		internal HtmlGenericControl CreateCssLink(string cssUrl) {
			if (String.IsNullOrEmpty(cssUrl)) return null;

			return CreateResolveClientCssLink(ResolveClientUrl(cssUrl));

		}

		internal static HtmlGenericControl CreateResolveClientCssLink(string resolveClientCssUrl) {
			if (String.IsNullOrEmpty(resolveClientCssUrl)) return null;
			var link = new HtmlGenericControl("link");
			link.Attributes["href"] = resolveClientCssUrl;
			link.Attributes["type"] = "text/css";
			link.Attributes["rel"] = "Stylesheet";
			link.Attributes["rev"] = "Stylesheet";
			return link;
		}
		protected void AddLinkCssControl(string cssUrl) {
			try {
				HtmlGenericControl link = CreateCssLink(cssUrl);
				if (link == null) return;
				if (Page.Header != null) {
					Page.Header.Controls.Add(link);
				}

				// ReSharper disable EmptyGeneralCatchClause
			} catch { }
			// ReSharper restore EmptyGeneralCatchClause
		}

		protected virtual string StyleSheetFileName {
			get { return String.Empty; }
		}
		[DefaultValue("~/style/simple/sppaging-ui.css")]

		public virtual string CssFileName { get; set; }

		protected virtual void CreateClientObjectAtRender(HtmlTextWriter writer) {
		}

		protected override void Render(HtmlTextWriter writer) {
			if (!Visible) return;
			base.Render(writer);
			if (!DesignMode) {
				CreateClientObjectAtRender(writer);
				if (_properties != null && _properties.Count > 0) {
					BeginScriptTag(writer);
					foreach (var pair in _properties) {
						writer.Write(String.Format("{0}.{1}='{2}';", ClientName, pair.Key, HttpContext.Current.Server.HtmlEncode(pair.Value)));
					}
					EndScriptTag(writer);
				}
			}
		}

		private List<KeyValuePair<string, string>> _properties;
		public void AddClientProperty(string key, string value) {
			if (_properties == null) _properties = new List<KeyValuePair<string, string>>();
			_properties.Add(new KeyValuePair<string, string>(key, value));
		}

		protected void InitForEffect(IEffectControl effectControl) {
			effectControl.DisplayEffect = Effect.Normal;
			effectControl.StepEffect = 1;
			effectControl.TimeEffect = 5;
		}

		protected bool IncludeScriptOnLoad(Type type, string key, string resourceUrl, params string[] includesLib) {
			if (IsLibraryWebControlsCallback)
				return false;
			if (String.IsNullOrEmpty(resourceUrl)) {
				if (!Page.ClientScript.IsClientScriptBlockRegistered(type, key)) {
					if (includesLib != null) {
						foreach (string lib in includesLib) {
							IncludeJavascriptCore(lib);
						}
					}
					Page.ClientScript.RegisterClientScriptBlock(type, key, String.Empty, false);
					if (!String.IsNullOrEmpty(CssFileName)) {
						AddLinkCssControl(CssFileName);
					}
				} else {
					return false;
				}

			} else
				if (!Page.ClientScript.IsClientScriptIncludeRegistered(type, key)) {
					if (includesLib != null) {
						foreach (string lib in includesLib) {
							IncludeJavascriptCore(lib);
						}
					}
					var resource = Page.ClientScript.GetWebResourceUrl(type, resourceUrl);
					Page.ClientScript.RegisterClientScriptInclude(type, key, resource);
					if (!String.IsNullOrEmpty(CssFileName)) {
						AddLinkCssControl(CssFileName);
					}
				} else {
					return false;
				}
			return true;
		}
	}
}
